home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <X11/StringDefs.h>
- #include <X11/Intrinsic.h>
- #include <Xm/Xm.h>
- #include <Xm/DrawingA.h>
- #include <X11/Xutil.h>
- #include <X11/cursorfont.h>
- #include "defs.h"
- #include "funcs.h"
-
- #ifndef __GNUC__
- #define inline
- #endif
-
- typedef struct Grid_t {
- unsigned int id;
- unsigned short color;
- } Grid_t;
-
- typedef struct Point_t {
- int x;
- int y;
- } Point_t;
-
- inline static void FindRectangle(image_data_t *data, Grid_t **grid, double *q,
- double *p, int mod_max, int id, int n_p, int n_q);
- inline static void FillRectangle(image_data_t *data, Grid_t **grid,
- Point_t *points, int color, int id);
- inline static int GetColor(image_data_t *data, Grid_t **grid, int n_p, int n_q,
- double q_val, double p, int mod_max, int id);
- inline static void DrawSetPoint(image_data_t *data, Grid_t **grid, int n_p,
- int n_q, int color, int id);
-
- void
- CreateImage(
- Widget w,
- image_data_t *data)
- {
- double delta_p, delta_q;
- int n_p, n_q, color, mod_max, id;
- double *q, *p;
- Grid_t **grid;
-
- XSetForeground(XtDisplay(w), data->gc, 1);
- XFillRectangle(XtDisplay(w), XtWindow(data->area), data->gc, 0, 0,
- data->width, data->height);
- XDefineCursor(XtDisplay(data->area), XtWindow(data->area),
- data->clock_cursor);
- XFlush(XtDisplay(data->area));
- InitBuffer(data);
- delta_p = (data->p_max - data->p_min) / (data->width - 1);
- delta_q = (data->q_max - data->q_min) / (data->height - 1);
- mod_max = data->max_color - 1;
- q = (double *)ALLOCATE_LOCAL(data->height * sizeof(double));
- p = (double *)ALLOCATE_LOCAL(data->width * sizeof(double));
- grid = (Grid_t **)ALLOCATE_LOCAL(data->height * sizeof(Grid_t *));
- for (n_q = 0; n_q < data->height; ++n_q)
- {
- grid[n_q] = (Grid_t *)ALLOCATE_LOCAL(data->width *
- sizeof(Grid_t));
- for (n_p = 0; n_p < data->width; ++n_p)
- grid[n_q][n_p].id = 0;
- q[n_q] = data->q_min + n_q * delta_q;
- }
- for (n_p = 0; n_p < data->width; ++n_p)
- p[n_p] = data->p_min + n_p * delta_p;
- id = 1;
- for (n_p = 0; n_p < data->width; ++n_p)
- {
- n_q = data->height - 1;
- while (n_q >= 0)
- {
- while (n_q >= 0 && grid[n_q][n_p].id)
- --n_q;
- if (n_q >= 0)
- {
- FindRectangle(data, grid, q, p, mod_max,
- id, n_p, n_q);
- ++id;
- --n_q;
- }
- }
- }
- FlushBuffer(w, data);
- DEALLOCATE_LOCAL((char *)q);
- DEALLOCATE_LOCAL((char *)p);
- for (n_q = 0; n_q < data->height; ++n_q)
- DEALLOCATE_LOCAL((char *)grid[n_q]);
- DEALLOCATE_LOCAL((char *)grid);
- XDefineCursor(XtDisplay(data->area), XtWindow(data->area),
- data->normal_cursor);
- }
-
- inline static void
- FindRectangle(
- image_data_t *data,
- Grid_t **grid,
- double *q,
- double *p,
- int mod_max,
- int id,
- int n_p,
- int n_q)
- {
- int color, x, y, width, height, old_n_p, old_n_q;
- int point_count;
- Point_t points[4];
- int direction_count = 0;
- int not_collide;
- int found_color;
- static Point_t direction[4] = {{1, 0}, {0, -1}, {-1, 0}, {0, 1}};
-
- color = GetColor(data, grid, n_p, n_q, q[n_q], p[n_p], mod_max, id);
- width = data->width;
- height = data->height;
- old_n_p = points[0].x = n_p;
- old_n_q = points[0].y = n_q;
- point_count = 1;
- do
- {
- x = n_p + direction[direction_count].x;
- y = n_q + direction[direction_count].y;
- while (x >= 0 && x < width &&
- y >= 0 && y < height &&
- (not_collide = grid[y][x].id != id) &&
- (grid[y][x].id > 0 ? grid[y][x].color != color : 1) &&
- color == (found_color = GetColor(data, grid, x, y, q[y],
- p[x], mod_max, id)))
- {
- n_p = x;
- n_q = y;
- x = n_p + direction[direction_count].x;
- y = n_q + direction[direction_count].y;
- }
- if (abs(n_p - old_n_p) <= 1 && abs(n_q - old_n_q) <= 1)
- return;
- old_n_p = n_p;
- old_n_q = n_q;
- points[point_count].x = n_p;
- points[point_count].y = n_q;
- point_count = (point_count + 1) % 4;
- direction_count = (direction_count + 1) % 4;
- } while (not_collide);
- FillRectangle(data, grid, points, color, id);
- }
-
- inline static void
- FillRectangle(
- image_data_t *data,
- Grid_t **grid,
- Point_t *points,
- int color,
- int id)
- {
- int i, j;
- int x0, y0, x1, y1;
-
- x1 = x0 = points[0].x;
- y1 = y0 = points[0].y;
- for (i = 1; i < 4; ++i)
- {
- if (points[i].x > x1)
- x1 = points[i].x;
- else
- if (points[i].x < x0)
- x0 = points[i].x;
- if (points[i].y > y1)
- y1 = points[i].y;
- else
- if (points[i].y < y0)
- y0 = points[i].y;
- }
- ++x0;
- ++y0;
-
- BufferRectangle(data, color, x0, y0, x1, y1);
- for (i = x0; i < x1; ++i)
- for (j = y0; j < y1; ++j)
- {
- grid[j][i].color = color;
- grid[j][i].id = id;
- }
- }
-
-
- inline static int
- GetColor(
- image_data_t *data,
- Grid_t **grid,
- int n_p,
- int n_q,
- double q_val,
- double p,
- int mod_max,
- int id)
- {
- int k, K, M, color;
- double x, y, new_x, r, x_2, y_2;
-
- if (grid[n_q][n_p].id > 0)
- return grid[n_q][n_p].color;
- k = 0;
- x = 0.0;
- y = 0.0;
- K = data->K;
- M = data->M;
- do
- {
- x_2 = x * x;
- y_2 = y * y;
- new_x = x_2 - y_2 + p;
- y = 2 * x * y + q_val;
- x = new_x;
- ++k;
- r = x_2 + y_2;
- } while (r <= M && k < K);
- if (k == data->K)
- color = 0;
- else
- color = k % mod_max + 1;
- DrawSetPoint(data, grid, n_p, n_q, color, id);
-
- return color;
- }
-
- inline static void
- DrawSetPoint(
- image_data_t *data,
- Grid_t **grid,
- int n_p,
- int n_q,
- int color,
- int id)
- {
- BufferPoint(data->area, data, color, n_p, n_q);
- grid[n_q][n_p].color = color;
- grid[n_q][n_p].id = id;
- }
-